#include "global.h"


#define WRDATA     	(1)
#define POLLACK     	(2)
#define RDDATA      	(3)
#define SETRDADDR   	(4)

#define IICBUFSIZE 32

byte I2CBuf[IICBUFSIZE];
int I2CBufNum;
int I2CStatus;
int I2CMode;
int I2CIdx;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PollI2C(void)
{
	uint iicSt,i;
	if(rIICCON & 0x10)                  //Tx/Rx Interrupt Enable
	{
		iicSt = rIICSTAT; 
		if(iicSt & 0x8){}                   //When bus arbitration is failed.
		if(iicSt & 0x4){}                   //When a slave address is matched with IICADD
		if(iicSt & 0x2){}                   //When a slave address is 0000000b
		if(iicSt & 0x1){}                   //When ACK isn't received

		switch(I2CMode)
		{
			case POLLACK:
				I2CStatus = iicSt;
			break;

			case RDDATA:
				if((I2CBufNum--)==0)
				{
					I2CBuf[I2CIdx++] = rIICDS;
					rIICSTAT = 0x90;       //Stop MasRx condition 
					rIICCON  = 0xaf;       //Resumes IIC operation.
					Delay(1);                  //Wait until stop condtion is in effect.\
					break;    
				}      
				I2CBuf[I2CIdx++] = rIICDS;
				//The last data has to be read with no ack.
				if((I2CBufNum)==0)
				rIICCON = 0x2f;                 //Resumes IIC operation with NOACK.  
				else 
				rIICCON = 0xaf;                 //Resumes IIC operation with ACK
			break;

			case WRDATA:
				if((I2CBufNum--)==0)
				{
					rIICSTAT = 0xd0;                //stop MasTx condition 
					rIICCON  = 0xaf;                //resumes IIC operation.
					Delay(1);                       //wait until stop condtion is in effect.
					//The pending bit will not be set after issuing stop condition.
					break;    
				}
				rIICDS = I2CBuf[I2CIdx++];  //I2CBuf[0] has dummy.
				for(i=0;i<10;i++);                   //for setup time until rising edge of IICSCL
				rIICCON = 0xaf;                     //resumes IIC operation.
			break;

			case SETRDADDR:
				if((I2CBufNum--)==0)
				break;                  //IIC operation is stopped because of IICCON[4]    
				rIICDS = I2CBuf[I2CIdx++];
				for(i=0;i<10;i++);          //for setup time until rising edge of IICSCL
				rIICCON = 0xaf;             //resumes IIC operation.
			break;

			default:
			break;      
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetupI2COV9620(void)
{
	//GPE15:IICSDA , GPE14:IICSCL 
	rGPECON&=(~(((uint)0xa)<<28));
	rGPECON|=(((uint)0xa)<<28);      
	rGPEUP&=(~(0x3<<15));

	//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
	// If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz
	//rIICCON = (1<<7) | (1<<6) | (1<<5) | (0xf);
	rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);

	rIICADD =0x10;                //2440 slave address = [7:1]
	rIICSTAT=0x10;                //IIC bus data output enable(Rx/Tx)
	rIICLC=(1<<2)|(1);  	     // Filter enable, 15 clocks SDA output delay       added by junon

	Delay(300);

	//pISR_IIC=(unsigned)Interrupt_I2C;
	//EnableIrq(BIT_IIC);
	//ClearPending(BIT_IIC);

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*************************[ Wr24C080 ]****************************
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void I2CWriteOV9620(byte slvAddr,byte addr,byte *data,int len)
{
	int idx0;
	I2CMode=WRDATA;
	I2CIdx=0;
	I2CBuf[0]=addr;
	for(idx0=0;idx0<len;idx0++)
	I2CBuf[idx0+1]=data[idx0];
	I2CBufNum=len+1;
    
	rIICDS=slvAddr;
	rIICSTAT=0xf0;
	while(I2CBufNum!=-1)
	PollI2C();

	rIICSTAT=0xd0;                    //Stop MasTx condition 
	rIICCON=0xaf;                    //Resumes IIC operation. 
	Delay(1);                       	 //Wait until stop condtion is in effect.
	
}
        
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//**********************[ Rd24C080 ] ***********************************
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void I2CReadOV9620(byte slvAddr,byte addr,byte *data,int len)
{
	int idx0;
	I2CMode=WRDATA;
	I2CIdx=0;
	I2CBuf[0]=addr;
	I2CBufNum=1;
    
	rIICDS=slvAddr;
	rIICSTAT=0xf0;
	while(I2CBufNum!=-1)
	PollI2C();

	//rIICSTAT=0xd0;                    //Stop MasTx condition 
	//rIICCON=0xaf;                    //Resumes IIC operation. 

	I2CMode=RDDATA;
	I2CIdx=0;
	I2CBufNum=len;

	rIICDS=slvAddr;
	rIICSTAT=0xb0;               //MasRx,Start
	rIICCON=0xaf;               //Resumes IIC operation.   
	while(I2CBufNum!=-1)
	PollI2C();

	for(idx0=0;idx0<len;idx0++)
	data[idx0]=I2CBuf[idx0+1];
}
